﻿using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.Models;
using AJWPFAdmin.Core.HardwareSDKS.VzClient;
using AJWPFAdmin.Core.Logger;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Mvvm;
using AJWPFAdmin.Core.Utils;
using EntranceGuardStatistic.Modules.Main.Views;
using AJWPFAdmin.Services.EF;
using Masuit.Tools;
using MaterialDesignThemes.Wpf;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Formats.Asn1;
using System.Linq;
using System.Net;
using System.Reflection.Metadata;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using static AJWPFAdmin.Core.ExceptionTool;
using AJWPFAdmin.Core.HardwareSDKS.HIKVision;
using System.Windows.Data;
using System.Windows.Media;

namespace EntranceGuardStatistic.Modules.Main.ViewModels
{
    public partial class DeviceScreenViewModel : ViewModelBase
    {

        private Visibility _emptyInfoVisibility;
        public Visibility EmptyInfoVisibility
        {
            get { return _emptyInfoVisibility; }
            set { SetProperty(ref _emptyInfoVisibility, value); }
        }

        private List<DeviceInfo> _deviceSource;


        private ObservableCollection<DeviceInfo> _devices;
        public ObservableCollection<DeviceInfo> DeviceList
        {
            get { return _devices; }
            set { SetProperty(ref _devices, value); }
        }


        private DelegateCommand<Grid> _cameraContainerLoadCmd;
        public DelegateCommand<Grid> CameraContainerLoadCmd =>
            _cameraContainerLoadCmd ?? (_cameraContainerLoadCmd = new DelegateCommand<Grid>(ExecuteCameraContainerLoadCmd));

        void ExecuteCameraContainerLoadCmd(Grid parameter)
        {
            var worker = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            _setupEvent.Publish(_setupProgressModel);

            worker.DoWork += (_, e) =>
            {
                worker.ReportProgress(0, "初始化设备...");

                var watchhouseList = db.Watchhouses.Include(p => p.Passageways)
                    .Select(p => new
                    {
                        p.Id,
                        p.Name,
                        p.Code,
                        Passageways = p.Passageways.Where(q => q.CountCarEnable)
                        .OrderBy(q => q.Code).Select(q => new
                        {
                            q.Id,
                            q.Name,
                            q.Code,
                            q.Direction
                        })
                    }).Where(p => p.Passageways.Any()).ToList();


                var watchhouseIds = watchhouseList.Select(p => p.Id).ToList();

                var list = db.Devices.Where(p => watchhouseIds.Contains(p.WatchhouseId))
                    .AsNoTracking().OrderBy(p => p.Type).ToList();

                if (list.Any(p => p.Type == DeviceType.车牌识别相机_臻识))
                {
                    if (VzClientSDK.VzLPRClient_Setup() != 0)
                    {
                        _logger.Error("臻识SDK初始化失败");
                    }
                }

                if (list.Any(p => p.Type == DeviceType.监控相机_海康))
                {
                    if (!CHCNetSDK.NET_DVR_Init())
                    {
                        _logger.Error("海康SDK初始化失败");
                    }
                }

                var matchedDeviceList = new List<DeviceInfo>();

                foreach (var wh in watchhouseList)
                {
                    foreach (var pw in wh.Passageways)
                    {
                        var devices = list
                        .Where(p => p.WatchhouseId == wh.Id && p.PassagewayId == pw.Id).ToList();
                        if (devices.Count == 0)
                        {
                            continue;
                        }
                        foreach (var device in devices)
                        {
                            worker.ReportProgress(0, $"加载 {wh.Name}>{pw.Name}...");
                            var df = (DeviceInfo)device;
                            df.Direction = pw.Direction;
                            df.WatchhouseId = wh.Id;
                            df.WatchhouseCode = wh.Code;
                            df.WatchhouseName = wh.Name;
                            df.PassagewayId = pw.Id;
                            df.PassagewayCode = pw.Code;
                            df.PassagewayName = pw.Name;

                            matchedDeviceList.Add(df);
                        }
                    }
                }

                var count = matchedDeviceList.Count;

                for (int i = 0; i < count; i++)
                {
                    var item = matchedDeviceList.ElementAt(i);
                }

                e.Result = matchedDeviceList;

            };
            worker.ProgressChanged += (_, e) =>
            {
                _setupProgressModel.ProgressText = e.UserState?.ToString();
                _setupEvent.Publish(_setupProgressModel);
            };
            worker.RunWorkerCompleted += async (_, e) =>
            {
                if (e.Error != null)
                {
                    _setupProgressModel.ProgressText = $"设备加载失败:{e.Error.Message}";
                    _setupEvent.Publish(_setupProgressModel);
                    await Task.Delay(2000);

                    _setupProgressModel.Loading = false;
                    _setupEvent.Publish(_setupProgressModel);
                    return;
                }

                _setupProgressModel.Loading = false;
                //_setupProgressModel.Completed = true;

                _deviceSource = e.Result as List<DeviceInfo>;

                _setupProgressModel.Devices = _deviceSource;

                _setupEvent.Publish(_setupProgressModel);

                DeviceList.AddRange(_deviceSource);

                EmptyInfoVisibility = DeviceList.Count == 0 ? Visibility.Visible : Visibility.Collapsed;

                
                if (DeviceList.Count > 0)
                {
                    var width = (parameter.ActualWidth - 16) / 2d;
                    var height = (9d / 16d) * width;

                    parameter.ColumnDefinitions.AddRange(
                        new ColumnDefinition(),
                        new ColumnDefinition()
                    );


                    var devCount = DeviceList.Count;

                    var rowCount = Convert.ToInt32(Math.Ceiling((decimal)DeviceList.Count / (decimal)parameter.ColumnDefinitions.Count));
                    // 至少2行
                    if (rowCount < 2)
                    {
                        rowCount = 2;
                    }

                    for (int i = 0; i < rowCount; i++)
                    {
                        parameter.RowDefinitions.AddRange(new RowDefinition
                        {
                            Height = new GridLength(height, GridUnitType.Pixel)
                        });
                    }


                    var r = 0;
                    var c = 0;
                    for (int i = 0; i < devCount; i++)
                    {
                        var ui = CreateCommonDeviceUI(DeviceList[i]);
                        Grid.SetRow(ui, r);
                        Grid.SetColumn(ui, c);
                        parameter.Children.Add(ui);

                        if ((i + 1) % 2 == 0)
                        {
                            c = 0;
                            r++;
                            continue;
                        }

                        c++;
                    }
                }
            };

            worker.RunWorkerAsync();
        }

        private UIElement CreateCommonDeviceUI(DeviceInfo dev)
        {
            
            var card = new Card
            {
                Margin = new Thickness(4),
                DataContext = dev,
            };

            ElevationAssist.SetElevation(card, Elevation.Dp4);

            card.MouseEnter += (sender, e) =>
            {
                (((Card)sender).DataContext as DeviceInfo).OnMouseEnterCmd.Execute();
            };
            card.MouseLeave += (sender, e) =>
            {
                (((Card)sender).DataContext as DeviceInfo).OnMouseLeaveCmd.Execute();
            };
            var brush = (SolidColorBrush)new BrushConverter().ConvertFrom("#80000000");
            var drawerHost = new DrawerHost
            {
                TopDrawerBackground = brush,
                BottomDrawerBackground = brush
            };

            drawerHost.SetBinding(DrawerHost.IsBottomDrawerOpenProperty, new Binding(nameof(DeviceInfo.MouseHover))
            {
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            });
            drawerHost.SetBinding(DrawerHost.IsTopDrawerOpenProperty, new Binding(nameof(DeviceInfo.MouseHover))
            {
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            });

            var topDrawerContent = new StackPanel
            {
                Margin = new Thickness(8),
                Orientation = Orientation.Horizontal,
            };
            var textBlockForeground
                = Application.Current.FindResource("PrimaryHueLightForegroundBrush") as SolidColorBrush;
            var watchhouseTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            watchhouseTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.WatchhouseName)));
            topDrawerContent.Children.Add(watchhouseTextblock);

            topDrawerContent.Children.Add(new TextBlock
            {
                Margin = new Thickness(4, 0, 4, 0),
                FontSize = 16,
                Foreground = textBlockForeground,
                Text = ">"
            });

            var passagewayTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            passagewayTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.PassagewayName)));
            topDrawerContent.Children.Add(passagewayTextblock);

            topDrawerContent.Children.Add(new TextBlock
            {
                Margin = new Thickness(4, 0, 4, 0),
                FontSize = 16,
                Foreground = textBlockForeground,
                Text = ">"
            });

            var codeTextblock = new TextBlock
            {
                FontSize = 16,
                Foreground = textBlockForeground,
            };
            codeTextblock.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.Code)));
            topDrawerContent.Children.Add(codeTextblock);

            drawerHost.TopDrawerContent = topDrawerContent;

            var bottomDrawerContent = new Grid();

            bottomDrawerContent.ColumnDefinitions.AddRange(new ColumnDefinition(), new ColumnDefinition());
            bottomDrawerContent.RowDefinitions.Add(new RowDefinition());

            var bottomDrawerStackPanel = new StackPanel
            {
                Margin = new Thickness(8),
                HorizontalAlignment = HorizontalAlignment.Right,
                Orientation = Orientation.Horizontal,
            };

            if (dev is VzCarIdentificationDevice)
            {
                var openBtn = new Button { Content = "开闸" };
                openBtn.SetBinding(Button.CommandProperty, new Binding(nameof(VzCarIdentificationDevice.ToggleSwitchCmd)));
                openBtn.CommandParameter = true ;
                bottomDrawerStackPanel.Children.Add(openBtn);

                var closeBtn = new Button
                {
                    Margin = new Thickness(16, 0, 16, 0),
                    Content = "关闸"
                };
                closeBtn.SetBinding(Button.CommandProperty, new Binding(nameof(VzCarIdentificationDevice.ToggleSwitchCmd)));
                closeBtn.CommandParameter = false;
                bottomDrawerStackPanel.Children.Add(closeBtn);
            }

            var msgTxt = new TextBlock
            {
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(4, 0, 4, 0),
                Foreground = (SolidColorBrush)Application.Current.FindResource("AJWhite")
            };
            msgTxt.SetBinding(TextBlock.TextProperty, new Binding(nameof(DeviceInfo.Message)));
            bottomDrawerContent.Children.Add(msgTxt);
            bottomDrawerContent.Children.Add(bottomDrawerStackPanel);
            Grid.SetColumn(bottomDrawerStackPanel, 1);

            drawerHost.BottomDrawerContent = bottomDrawerContent;

            var imgBox = new Image
            {
                Stretch = Stretch.Fill
            };

            imgBox.Loaded += (s, e) =>
            {
                dev.DeviceControlLoadCmd.Execute(imgBox);
            };

            drawerHost.Content = imgBox;

            card.Content = drawerHost;

            return card;
        }

        private DeviceSetupProgressModel _setupProgressModel;

        private DbService db;
        private DeviceSetupProgressEvent _setupEvent;
        private IEventAggregator _eventAggregator;
        private AJLog4NetLogger _logger;


        public DeviceScreenViewModel(DbService dbIns, IEventAggregator eventAggregator,
            AJLog4NetLogger logger)
        {
            db = dbIns;
            _logger = logger;
            DeviceList = new ObservableCollection<DeviceInfo>();
            _setupProgressModel = new DeviceSetupProgressModel
            {
                Loading = true,
            };
            DeviceInfo.EventAggregator = _eventAggregator = eventAggregator;
            _setupEvent = eventAggregator.GetEvent<DeviceSetupProgressEvent>();
            eventAggregator.GetEvent<ApplicationExitEvent>().Subscribe(() =>
            {
                foreach (DeviceInfo deviceInfo in DeviceList)
                {
                    try
                    {
                        deviceInfo.Close();
                    }
                    catch (Exception)
                    {

                    }
                }

                if (DeviceList.Any(p => p.Type == DeviceType.车牌识别相机_臻识))
                {
                    VzClientSDK.VzLPRClient_Cleanup();
                }
                if (DeviceList.Any(p => p.Type == DeviceType.监控相机_海康))
                {
                    CHCNetSDK.NET_DVR_Cleanup();
                }
            });
        }
    }

    public class DeviceTemplateSelector : DataTemplateSelector
    {
        public DataTemplate CCTVCamera { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item == null)
            {
                return null;
            }
            if (item is not DeviceInfo device)
            {
                return null;
            }

            return CCTVCamera;
        }
    }
}
